from decimal import Decimal
from logging import log

from django.db import transaction
from rest_framework import serializers
from goods.models import SKU
from goods.serializers import SKUSerializer
from orders.models import OrderInfo, OrderGoods
from django_redis import get_redis_connection
from datetime import datetime

from users.serializers import UserSerialzier


class CartSKUSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField()

    class Meta:
        model = SKU
        fields = '__all__'

class OrderInfoSerializer(serializers.ModelSerializer):

    user = UserSerialzier

    class Meta:
        model = OrderInfo
        fields = ('user')


class OrderShowSerializers(serializers.Serializer):
    freight = serializers.DecimalField(label='运费', max_digits=10, decimal_places=2)
    skus = CartSKUSerializer(many=True)


class SaveOrderSerializer(serializers.ModelSerializer):
    """
    下单数据序列化器
    """

    class Meta:
        model = OrderInfo
        fields = ('order_id', 'address', 'pay_method')
        read_only_fields = ('order_id',)
        extra_kwargs = {
            'address': {
                'write_only': True,
                'required': True,
            },
            'pay_method': {
                'write_only': True,
                'required': True
            }
        }

    # @transaction.atomic
    def create(self, validated_data):
        """保存订单"""

        # 1、获取用户
        user = self.context['request'].user
        # 2、获取支付方式和地址
        pay_method = validated_data['pay_method']
        address = validated_data['address']
        # 3、生成订单编号
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + '%09d' % user.id
        # 引入事务
        with transaction.atomic():
            # 这部分代码会在事务中执行
            # 设置保存点
            save_point = transaction.savepoint()
            try:
                # 4、初始化生成订单基本信息表
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,  # 总量初始化0
                    total_amount=Decimal(0),
                    freight=Decimal(10),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
                        'CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID']

                )
                # 5、查询缓存获取选中状态商品
                # 提取redis中选中状态的sku_id
                conn = get_redis_connection('cart')
                # 获取商品数据量
                sku_count = conn.hgetall('cart_%s' % user.id)  # {'sku_id':'count'}
                sku_ids = conn.smembers('cart_selectes_%s' % user.id)

                order_dict = {}
                for sku_id, count in sku_count.items():
                    if sku_id in sku_ids:
                        order_dict[int(sku_id)] = int(count)

                # 查询选中状态的商品对象 查询集   惰性执行  缓存
                # skus = SKU.objects.filter(id__in=sku_ids)
                # 6、遍历选中状态的商品
                for sku_id in sku_ids:
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        old_stock = sku.stock  # 原始库存
                        old_sales = sku.sales
                        count = order_dict[sku.id]
                        # 7、判断当前下订单的商品的库存数否充足
                        if count > old_stock:
                            raise serializers.ValidationError('库存不足')

                        # 8、减少sku商品库存
                        # sku.stock = old_stock - count
                        # 9、增加销量
                        new_sales = old_sales + count
                        new_stock = old_stock - count
                        res = SKU.objects.filter(id=sku.id, stock=old_stock).update(stock=new_stock, sales=new_sales)
                        if res == 0:
                            continue
                        # 10、修改spu表总销量
                        sku.goods.sales += count
                        sku.goods.save()
                        # 11、修改订单基本信息表中总量和总价
                        order.total_count += count
                        order.total_amount += (sku.price * count)
                        # 12、创建订单商品表
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=count,
                            price=sku.price,

                        )
                        break

                order.total_amount += order.freight
                order.save()
            except:
                # 回滚到保存点
                transaction.savepoint_rollback(save_point)

            else:
                # 提交从保存点到当前状态的所有数据库事务操作
                transaction.savepoint_commit(save_point)

                # 13、清除购物车，删除redis选中状态的商品
                conn.hdel('cart_%s' % user.id, *sku_ids)
                conn.srem('cart_selectes_%s' % user.id, *sku_ids)
                # 14、返回结果
                return order


class OrderGoodsSerializer(serializers.ModelSerializer):

    sku = SKUSerializer()
    price = serializers.IntegerField(min_value=0, read_only=True)
    count = serializers.IntegerField(min_value=0, read_only=True)

    class Meta:
        model = OrderGoods
        fields = ['sku', "price", 'count']


class UserOrderSerializer(serializers.ModelSerializer):
    skus = OrderGoodsSerializer(many=True)

    class Meta:
        model = OrderInfo
        fields = ['order_id', 'create_time', 'total_amount', 'freight', 'pay_method', 'status', 'skus']


class GoodsCommentsSerializer(serializers.ModelSerializer):
    sku = SKUSerializer()

    class Meta:
        model = OrderGoods
        fields = ['sku', 'price']
        read_only_fields = ['price']


class GoodsCommentSerializer(serializers.ModelSerializer):
    # sku = serializers.IntegerField(min_value=1)
    # order = serializers.IntegerField(min_value=1)
    class Meta:
        model = OrderGoods
        # fields = "__all__"
        exclude = ('price',)

    def validate(self, attrs):
        # 验证order_id
        try:
            order_good = OrderInfo.objects.filter(order_id=attrs['order'])
        except:
            raise serializers.ValidationError("订单不存在")

        # 验证SKU_id,是否存在
        try:
            print(attrs['sku'])
            SKU.objects.get(id=attrs['sku'].id)
        except:
            raise serializers.ValidationError("订单商品不存在")
        # 验证评论信息
        if len(attrs['comment']) < 5:
            raise serializers.ValidationError("评论字数少于5个字")

        # 验证分数
        if attrs['score'] < 0 or attrs['score'] > 5:
            raise serializers.ValidationError("评分数超出范围")

        return attrs

    def update(self, instance, validated_data):
        try:
            instance.comment = validated_data['comment']
            instance.score = validated_data['score']
            instance.is_anonymous = validated_data['is_anonymous']
            instance.is_commented = True
            instance.save()
        except:
            raise serializers.ValidationError("数据库操作出错")
        else:
            # order_info = OrderInfo.objects.get(order_id = instance.order.order_id)
            order_goods = OrderGoods.objects.filter(order_id = instance.order.order_id ).all()
            for goods in order_goods:
                if not goods.is_commented:
                    break
            else:
                order = OrderInfo.objects.get(order_id = instance.order.order_id)
                order.status = 5
                order.save()
        return instance
